//---------------------------------------------------------------------------

#include "vcl_stl.h"
#pragma hdrstop

#include <algorithm>

#include "h_base.h"
#include "h_xml.h"
#include "h_global.h"
#include "h_lz77.h"
#include "h_lz77_old.h"
using namespace h_base;
using namespace h_xml;

#include "h_server.h"
#include "h_g.h"
#include "h_portal.h"
#include "h_i18n.h"
#include "h_progressbar.h"
#include "t_mainform.h"
#include "t_logform.h"
#include "t_ganttform.h"
#include "t_listform.h"
#include "t_batlistform.h"
//---------------------------------------------------------------------------

bool HServer::RefreshLocked = false;
static const char *ProtocolVersion = "SIMJIE0104";

void __fastcall HServer::RefreshComplete(HBatchIcon *Batch)
{
   h_g::WriteLog("Idx = %3d, HServer::RefreshComplete begin, "
      "RefreshLocked = %d, Entered = %d",
      Batch->Idx, RefreshLocked, Batch->Entered);

   if ( RefreshLocked || h_g::ExitFlag )
   {
      return;
   }

   Batch->Lock();
   HOutlineStatus OldOutlineStatus = Batch->OutlineStatus;
   HOutlineStatus NewOutlineStatus = Batch->NewOutlineStatus;
   Batch->OutlineStatus = NewOutlineStatus;

   h_g::WriteLog("Idx = %3d, Entered = %d, OldStartTime = %s, NewStartTime = %s",
      Batch->Idx, Batch->Entered, Batch->LastStartTime.c_str(),
      NewOutlineStatus.StartTime.c_str());

   if ( Batch->Entered && NewOutlineStatus.FullRefresh )
   {
      Batch->PaintingFlag = true;
      if ( Batch->LastStartTime != NewOutlineStatus.StartTime )
      {
         MainForm->LoadFromXmlTree(Batch->RefreshXml);
         h_g::WriteLog("Idx = %3d, LoadFromXmlTree completed", Batch->Idx);
         GanttForm->Clear();
      }
      else
      {
         MainForm->RefreshFromXmlTree(Batch->RefreshXml);
         h_g::WriteLog("Idx = %3d, RefreshFromXmlTree completed", Batch->Idx);
      }
      ListForm->Reload();
      if ( Batch->NavInfo.ServerIdx == Batch->Idx )
      {
         MainForm->GotoPage(Batch->NavInfo.GroupName,
            Batch->NavInfo.HScrollPosition, Batch->NavInfo.VScrollPosition);
         Batch->NavInfo.ServerIdx = -1;
      }
      Batch->LastStartTime = NewOutlineStatus.StartTime;
      Batch->LastRefreshTick = NewOutlineStatus.RefreshTick;
      MainForm->ProgressBar->ShowFlag = false;
      Batch->PaintingFlag = false;
   }

   Batch->Unlock();
   h_g::WriteLog("Idx = %3d, OldStatus = %d, OldStatusStr = %s, NewStatus = %d, NewStatusStr = %s",
      Batch->Idx, OldOutlineStatus.Status, OldOutlineStatus.StatusStr.c_str(),
      NewOutlineStatus.Status, NewOutlineStatus.StatusStr.c_str());

   if ( !Batch->Outline.Offline && OldOutlineStatus.Status != h_g::itUnknown &&
        ( OldOutlineStatus.Status != NewOutlineStatus.Status ||
          OldOutlineStatus.StatusStr != NewOutlineStatus.StatusStr ) )
   {
      UTF8String TmpStr;
      TmpStr.sprintf("'%s'", Batch->Outline.Caption.c_str());
      if ( NewOutlineStatus.AlarmType != "" ||
                NewOutlineStatus.Status == h_g::itFailed ||
                NewOutlineStatus.Status == h_g::itWaiting )
      {
         MainForm->Attention(TmpStr +
            UTF8String(h_g::I18nString("h_server:NEED_YOUR_ATTENTION")), true);
      }
      else if ( OldOutlineStatus.Status != NewOutlineStatus.Status &&
                NewOutlineStatus.Status == h_g::itSuccess &&
                !NewOutlineStatus.AutoSkip )
      {
         MainForm->Attention(TmpStr +
            UTF8String(h_g::I18nString("h_server:COMPLETED")), false);
      }
   }

   if ( !Batch->Outline.Offline &&
        ( OldOutlineStatus.Status != NewOutlineStatus.Status ||
          OldOutlineStatus.StatusStr != NewOutlineStatus.StatusStr ) )
   {
      MainForm->RefreshBatchColor(Batch->Idx);
   }

   BatListForm->Reload();
   h_g::WriteLog("Idx = %3d, HServer::RefreshComplete end", Batch->Idx);

}

void __fastcall HServer::LockRefresh(void)
{
   RefreshLocked = true;
}

void __fastcall HServer::UnlockRefresh(void)
{
   RefreshLocked = false;
}

bool __fastcall HServer::FuncChangeDate(HBatchIcon *Batch,
   const UTF8String &BatchDate, const UTF8String &NextBatchDate,
   const UTF8String &EndBatchDate, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ChangeDate", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ChangeDate", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ChangeDate", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sn|%s|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), BatchDate.c_str(), NextBatchDate.c_str(),
      EndBatchDate.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf),
       COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "ChangeDate", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "ChangeDate", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "ChangeDate");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncStartBatch(HBatchIcon *Batch,
   const UTF8String &BatchDate, const UTF8String &NextBatchDate,
   const UTF8String &EndBatchDate, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "StartBatch", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StartBatch", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StartBatch", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%s1|%s|%s|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Outline.Name.c_str(),
      BatchDate.c_str(), EndBatchDate.c_str(), NextBatchDate.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf),
       COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "StartBatch", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "StartBatch", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "StartBatch");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncPauseBatch(HBatchIcon *Batch,
   UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "PauseBatch", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "PauseBatch", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "PauseBatch", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%s2|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "PauseBatch", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "PauseBatch", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "PauseBatch");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncContinueBatch(HBatchIcon *Batch,
   UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ContinueBatch", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ContinueBatch", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ContinueBatch", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sB|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "ContinueBatch", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "ContinueBatch", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "ContinueBatch");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncStopBatch(HBatchIcon *Batch,
   UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "StopBatch", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StopBatch", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StopBatch", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%s3|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "StopBatch", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "StopBatch", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "StopBatch");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::ReadFileFromSocket(SOCKET Sock,
   char *ErrorStr, const char *FileName)
{
   int r;
   DWORD ErrCode;
   char Buf[8192 + 1];

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
         r, ErrCode);
      return false;
   }

   if ( Buf[0] == '1' )
   {
      r = HComm::Read(Sock, Buf, 8, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         return false;
      }
      Buf[8] = '\0';
      int ErrStrLen = h_base::HexStrToInt(Buf);
      if ( ErrStrLen > 200 )
      {
         ErrStrLen = 200;
      }
      r = HComm::Read(Sock, ErrorStr, ErrStrLen, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         return false;
      }
      ErrorStr[ErrStrLen] = '\0';
      return false;
   }

   r = HComm::Read(Sock, Buf + 1, 7, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
         r, ErrCode);
      return false;
   }

   Buf[8] = '\0';

   FILE *f = _wfopen(UnicodeString(UTF8String(FileName)).c_str(), L"wb");

   if ( f == NULL )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:CAN_NOT_CREATE"),
         FileName);
      return false;
   }

   int TotalLen = h_base::HexStrToInt(Buf);

   for( int i = 0; i < TotalLen; )
   {
      int Len;
      if( TotalLen - i >= 1024 )
         Len = 1024;
      else
         Len = TotalLen - i;
      r = HComm::Read(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         fclose(f);
         return false;;
      }
      fwrite(Buf, Len, 1, f);
      i += Len;
   }

   fclose(f);
   return true;
}

bool __fastcall HServer::ReadFileFromSocketDecompress(SOCKET Sock,
   char *ErrorStr, const char *BinFileName, const char *XmlFileName,
   bool &RepeatFlag, HBatchIcon *Batch, bool &ProgressFlag, bool OldFlag)
{
   int r;
   DWORD ErrCode;
   char *Buf = Batch->DecompressBuf;
   char *Buf2 = Batch->DecompressBuf + 1024 * 1024L + 1024 * 4;

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
         r, ErrCode);
      return false;
   }

   if ( Buf[0] == '1' )
   {
      r = HComm::Read(Sock, Buf, 8, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         return false;
      }
      Buf[8] = '\0';
      int ErrStrLen = h_base::HexStrToInt(Buf);
      if ( ErrStrLen > 200 )
      {
         ErrStrLen = 200;
      }
      r = HComm::Read(Sock, ErrorStr, ErrStrLen, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
            r, ErrCode);
         return false;
      }
      ErrorStr[ErrStrLen] = '\0';
      return false;
   }

   r = HComm::Read(Sock, Buf + 1, 7, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
         r, ErrCode);
      return false;
   }

   Buf[8] = '\0';

   RepeatFlag = ( Buf[0] == 'R' );
   bool DecompressFlag = ( Buf[1] == 'Y' );
   int TotalSize = StrToInt(Buf + 2);
   int Rate = 0;
   const char *FileName = RepeatFlag ? XmlFileName : BinFileName;

   ProgressFlag = false;

   if ( Batch->Entered && RepeatFlag && TotalSize >= 10 )
   {
      ProgressFlag = true;
      PostMessage(MainForm->Handle, HM_PROGRESS, 0, 0);
   }

   FILE *f = _wfopen(UnicodeString(UTF8String(FileName)).c_str(), L"wb");

   if ( f == NULL )
   {
      snprintf(ErrorStr, 200, h_g::I18nString("h_server:CAN_NOT_CREATE"),
         FileName);
      if ( Batch->Entered && ProgressFlag )
      {
         PostMessage(MainForm->Handle, HM_PROGRESS, 0, 1);
         ProgressFlag = false;
      }
      return false;
   }

   unsigned long DownloadLen = 0;

   for ( ; ; )
   {
      if ( RepeatFlag )
      {
         r = HComm::Read(Sock, Buf, 8, COMM_TIME_OUT, &ErrCode);
         if( r < 0 )
         {
            snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
               r, ErrCode);
            if ( Batch->Entered && ProgressFlag )
            {
               PostMessage(MainForm->Handle, HM_PROGRESS, 0, 1);
               ProgressFlag = false;
            }
            return false;
         }
         Buf[8] = '\0';
         int Len = h_base::HexStrToInt(Buf);
         if ( Len == 0 || h_g::ExitFlag )
         {
            break;
         }
         if ( !Batch->Entered && RepeatFlag )
         {
            snprintf(ErrorStr, 200, "%s", h_g::I18nString("h_server:USER_CANCEL"));
            fclose(f);
            if ( Batch->Entered && ProgressFlag )
            {
               PostMessage(MainForm->Handle, HM_PROGRESS, 0, 1);
               ProgressFlag = false;
            }
            return false;;
         }
         r = HComm::Read(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
         if( r < 0 )
         {
            snprintf(ErrorStr, 200, h_g::I18nString("h_server:READ_ERROR"),
               "outline_sock", r, ErrCode);
            fclose(f);
            if ( Batch->Entered && ProgressFlag )
            {
               PostMessage(MainForm->Handle, HM_PROGRESS, 0, 1);
               ProgressFlag = false;
            }
            return false;;
         }
         if ( h_g::ExitFlag )
         {
            break;
         }
         if ( !Batch->Entered && RepeatFlag )
         {
            snprintf(ErrorStr, 200, "%s", h_g::I18nString("h_server:USER_CANCELED"));
            fclose(f);
            if ( Batch->Entered && ProgressFlag )
            {
               PostMessage(MainForm->Handle, HM_PROGRESS, 0, 1);
               ProgressFlag = false;
            }
            return false;;
         }
         if ( DecompressFlag )
         {
            int Len2;
            if ( OldFlag )
            {
               Lz77DecompressBuf_old(Buf, Buf2, Len, &Len2);
            }
            else
            {
               Lz77DecompressBuf(Buf, Buf2, Len, &Len2);
            }
            fwrite(Buf2, Len2, 1, f);
            DownloadLen += Len2;
         }
         else
         {
            fwrite(Buf, Len, 1, f);
            DownloadLen += Len;
         }
         if ( Batch->Entered && ProgressFlag )
         {
            int DownloadSize = DownloadLen / 1024 / 1024;
            unsigned long NewRate = 95 * DownloadSize / TotalSize;
            if ( NewRate != Rate )
            {
               Rate = NewRate;
               PostMessage(MainForm->Handle, HM_PROGRESS, Rate, 0);
            }
         }
      }
      else
      {
         int TotalLen = h_base::HexStrToInt(Buf);
         for( int i = 0; i < TotalLen; )
         {
            int Len;
            if( TotalLen - i >= 1024 )
               Len = 1024;
            else
               Len = TotalLen - i;
            r = HComm::Read(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
            if( r < 0 )
            {
               snprintf(ErrorStr, 200, h_g::I18nString("h_server:INQUIRY_READ_LENGTH_ERROR"),
                  r, ErrCode);
               fclose(f);
               return false;;
            }
            fwrite(Buf, Len, 1, f);
            i += Len;
         }
         break;
      }
   }

   fclose(f);
   return true;
}

bool __fastcall HServer::FuncSkipJob(HBatchIcon *Batch,
   const UTF8String &Job, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "SkipJob", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "SkipJob", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "SkipJob", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%s5|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "SkipJob", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "SkipJob", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "SkipJob");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncRerunJob(HBatchIcon *Batch,
   const UTF8String &Job, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "RerunJob", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "RerunJob", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "RerunJob", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%s6|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "RerunJob", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "RerunJob", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "RerunJob");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncRestoreJob(HBatchIcon *Batch,
   const UTF8String &Job, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "RestoreJob", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "RestoreJob", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "RestoreJob", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sD|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "RestoreJob", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "RestoreJob", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "RestoreJob");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncStopJob(HBatchIcon *Batch,
   const UTF8String &Job, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "StopJob", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StopJob", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StopJob", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%s7|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "StopJob", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "StopJob", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "StopJob");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncStopAndSkipJob(HBatchIcon *Batch,
   const UTF8String &Job, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "StopAndSkipJob", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StopAndSkipJob", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "StopAndSkipJob", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sk|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "StopAndSkipJob", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "StopAndSkipJob", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "StopAndSkipJob");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

void __fastcall HServer::FuncViewLog(HBatchIcon *Batch,
   const UTF8String &Job, bool RestoreFlag)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   FILE *f = NULL;
   HXmlTree Xml;
   char TmpFile1[200 + 1];
   char TmpFile2[200 + 1];

   snprintf(TmpFile1, 200, "t1_%d_%ld", Batch->Idx, GetCurrentProcessId());
   snprintf(TmpFile2, 200, "t2_%d_%ld", Batch->Idx, GetCurrentProcessId());

   f = NULL;
   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ViewLog", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewLog", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewLog", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 4096, "%s8|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str(), RestoreFlag ? "r" : "");
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "ViewLog", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "ViewLog");
      goto error;
   }

   char TmpStr[500 + 1];
   snprintf(TmpStr, 500, h_g::I18nString("h_server:LOG_OF_JOB"), Job.c_str());
   LogForm->Caption = UTF8String(TmpStr);
   LogForm->Memo1->Lines->Clear();
   f = _wfopen(UnicodeString(UTF8String(TmpFile2)).c_str(), L"rb");

   if( f != NULL )
   {
      for( ; h_base::ReadLine(f, Buf, 4096) != -1; )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      fclose(f);
   }

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   LogForm->ShowModal();
   return;

error :

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   h_g::ShowMessage(UTF8String(Buf));

   if( f != NULL )
      fclose(f);

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);
}

void __fastcall HServer::FuncViewAdditionalLog(HBatchIcon *Batch,
   const UTF8String &Job)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   FILE *f;
   HXmlTree Xml;
   char TmpFile1[200 + 1];
   char TmpFile2[200 + 1];

   snprintf(TmpFile1, 200, "t1_%d_%ld", Batch->Idx, GetCurrentProcessId());
   snprintf(TmpFile2, 200, "t2_%d_%ld", Batch->Idx, GetCurrentProcessId());

   f = NULL;
   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ViewAdditionalLog", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewAdditionalLog", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewAdditionalLog", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 4096, "%sE|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "ViewAdditionalLog", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "ViewAdditionalLog");
      goto error;
   }

   char TmpStr[500 + 1];
   snprintf(TmpStr, 500, h_g::I18nString("h_server:ADDITIONAL_LOG_OF_JOB"), Job.c_str());
   LogForm->Caption = UTF8String(TmpStr);
   LogForm->Memo1->Lines->Clear();
   f = _wfopen(UnicodeString(UTF8String(TmpFile2)).c_str(), L"rb");

   if( f != NULL )
   {
      for( ; h_base::ReadLine(f, Buf, 4096) != -1; )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      fclose(f);
   }

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   LogForm->ShowModal();
   return;

error :

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   h_g::ShowMessage(UTF8String(Buf));

   if( f != NULL )
      fclose(f);

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);
}

void __fastcall HServer::FuncCalcCriticalPath(HBatchIcon *Batch)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   FILE *f;
   HXmlTree Xml;
   char TmpFile1[200 + 1];
   char TmpFile2[200 + 1];

   snprintf(TmpFile1, 200, "t1_%d_%ld", Batch->Idx, GetCurrentProcessId());
   snprintf(TmpFile2, 200, "t2_%d_%ld", Batch->Idx, GetCurrentProcessId());

   f = NULL;
   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "CalcCriticalPath", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "CalcCriticalPath", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "CalcCriticalPath", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 4096, "%sF|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "CalcCriticalPath", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "CalcCriticalPath");
      goto error;
   }

   LogForm->Caption = UTF8String(h_g::I18nString("h_server:CRITICAL_PATH"));
   LogForm->Memo1->Lines->Clear();
   f = _wfopen(UnicodeString(UTF8String(TmpFile2)).c_str(), L"rb");

   if( f != NULL )
   {
      for( ; h_base::ReadLine(f, Buf, 4096) != -1; )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      fclose(f);
   }

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   LogForm->ShowModal();
   return;

error :

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   h_g::ShowMessage(UTF8String(Buf));

   if( f != NULL )
      fclose(f);

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);
}

void __fastcall HServer::FuncViewSummary(HBatchIcon *Batch)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int TotalLen, Len, i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   FILE *f;
   HXmlTree Xml;
   char TmpFile1[200 + 1];
   char TmpFile2[200 + 1];

   snprintf(TmpFile1, 200, "t1_%d_%ld", Batch->Idx, GetCurrentProcessId());
   snprintf(TmpFile2, 200, "t2_%d_%ld", Batch->Idx, GetCurrentProcessId());

   f = NULL;
   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ViewSummary", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewSummary", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewSummary", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 4096, "%s9|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "ViewSummary", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "ViewSummary");
      goto error;
   }

   LogForm->Caption = UTF8String(h_g::I18nString("h_server:SUMMARY"));
   LogForm->Memo1->Lines->Clear();
   f = _wfopen(UnicodeString(UTF8String(TmpFile2)).c_str(), L"rb");

   if( f != NULL )
   {
      for( ; h_base::ReadLine(f, Buf, 4096) != -1; )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      fclose(f);
   }

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   LogForm->ShowModal();
   return;

error :

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   h_g::ShowMessage(UTF8String(Buf));

   if( f != NULL )
      fclose(f);

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);
}

bool __fastcall HServer::FuncLogin(HBatchIcon *Batch,
   const UTF8String &Id, const UTF8String &Password,
   const UTF8String &Auth, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "Login", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "Login", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "Login", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sA|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Id.c_str(), Password.c_str(), Auth.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "Login", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "Login", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      if ( Buf[0] == '2' )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:ACCESS_DENIED"));
      }
      else
      {
         ErrorString.sprintf(h_g::I18nString("h_server:LOGIN_FAIL"));
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   h_g::ShowMessage(ErrorString);
   return false;
}

void __fastcall HServer::FuncViewFailedJobList(HBatchIcon *Batch)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   FILE *f;
   HXmlTree Xml;
   char TmpFile1[200 + 1];
   char TmpFile2[200 + 1];

   snprintf(TmpFile1, 200, "t1_%d_%ld", Batch->Idx, GetCurrentProcessId());
   snprintf(TmpFile2, 200, "t2_%d_%ld", Batch->Idx, GetCurrentProcessId());

   f = NULL;
   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ViewFailedJobList", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewFailedJobList", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewFailedJobList", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 4096, "%s9|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "ViewFailedJobList", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "ViewFailedJobList");
      goto error;
   }

   LogForm->Caption = UTF8String(h_g::I18nString("h_server:FAILED_JOB_LIST"));
   LogForm->Memo1->Lines->Clear();
   f = _wfopen(UnicodeString(UTF8String(TmpFile2)).c_str(), L"rb");

   if( f != NULL )
   {
      if( h_base::ReadLine(f, Buf, 4096) != -1 )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      if( h_base::ReadLine(f, Buf, 4096) != -1 )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      if( h_base::ReadLine(f, Buf, 4096) != -1 )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      for( ; ; )
      {
         if( h_base::ReadLine(f, Buf, 4096) == -1 )
            break;
         if( memcmp(Buf, "Batch end time", 14) == 0 )
         {
            LogForm->Memo1->Lines->Add("");
            LogForm->Memo1->Lines->Add(UTF8String(Buf));
            break;
         }
         if( strstr(Buf, "|FAIL") != NULL ||
             strstr(Buf, "|UNKNOWN") != NULL ||
             strstr(Buf, "|SKIPPED") != NULL )
            LogForm->Memo1->Lines->Add(UTF8String(Buf));
      }
      fclose(f);
   }

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   LogForm->ShowModal();
   return;

error :

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   h_g::ShowMessage(UTF8String(Buf));

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);
}

struct HTop20Info
{
   string Name;
   string Time;
   string Line;
};

bool operator<(const HTop20Info &lhs, const HTop20Info &rhs)
{
   return lhs.Time > rhs.Time;
}

void __fastcall HServer::FuncViewTop20(HBatchIcon *Batch)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   FILE *f;
   HXmlTree Xml;
   char TmpFile1[200 + 1];
   char TmpFile2[200 + 1];

   snprintf(TmpFile1, 200, "t1_%d_%ld", Batch->Idx, GetCurrentProcessId());
   snprintf(TmpFile2, 200, "t2_%d_%ld", Batch->Idx, GetCurrentProcessId());

   f = NULL;
   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ViewTop20", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewTop20", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "ViewTop20", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 4096, "%s9|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "ViewTop20", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "ViewTop20");
      goto error;
   }

   LogForm->Caption = UTF8String(h_g::I18nString("h_server:TOP_20_JOB_LIST"));
   LogForm->Memo1->Lines->Clear();
   f = _wfopen(UnicodeString(UTF8String(TmpFile2)).c_str(), L"rb");

   if( f != NULL )
   {
      map<string, HTop20Info> Top20Map;
      h_base::ReadLine(f, Buf, 4096);
      h_base::ReadLine(f, Buf, 4096);
      if( h_base::ReadLine(f, Buf, 4096) != -1 )
         LogForm->Memo1->Lines->Add(UTF8String(Buf));
      for( ; ; )
      {
         if( h_base::ReadLine(f, Buf, 4096) == -1 )
            break;
         if( memcmp(Buf, "Batch end time", 14) == 0 )
         {
            break;
         }
         vector<string> StrVec;
         h_base::SplitString(Buf, '|', StrVec, true);
         if ( StrVec.size() < 5 )
         {
            continue;
         }
         const char *s = StrVec[0].c_str();
         if ( strchr(s, '(') != NULL )
         {
            continue;
         }
         const char *s2 = strchr(s, *h_g::JobNameDelimiter);
         if ( s2 != NULL )
         {
            if ( strchr(s2 + 1, ':') != NULL )
            {
               continue;
            }
         }
         HTop20Info Top20;
         Top20.Name = StrVec[0];
         Top20.Time = StrVec[3];
         Top20.Line = Buf;
         Top20Map[Top20.Name] = Top20;
      }
      fclose(f);
      vector<HTop20Info> Top20Vec;
      for ( map<string, HTop20Info>::iterator Iter = Top20Map.begin();
            Iter != Top20Map.end(); Iter++ )
      {
         Top20Vec.push_back(Iter->second);
      }
      sort(Top20Vec.begin(), Top20Vec.end());
      for ( int i = 0; i < 20 && i < Top20Vec.size(); i++ )
      {
         LogForm->Memo1->Lines->Add(UTF8String(Top20Vec[i].Line.c_str()));
      }
   }

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   LogForm->ShowModal();
   return;

error :

   DeleteFile(TmpFile1);
   DeleteFile(TmpFile2);
   h_g::ShowMessage(UTF8String(Buf));

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);
}

bool __fastcall HServer::FuncFireEvent(HBatchIcon *Batch,
   const UTF8String &EventName, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "FireEvent", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "FireEvent", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "FireEvent", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sC|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), EventName.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "FireEvent", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "FireEvent", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "FireEvent");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

void __fastcall HServer::FuncOutline(HBatchIcon *Batch)
{
   if ( RefreshLocked || h_g::ExitFlag || Batch->PaintingFlag )
   {
      return;
   }

   HBatchOutline &Outline = Batch->Outline;
   h_g::WriteLog("Idx = %3d, Batch = %p, HServer::FuncOutline begin", Batch->Idx, Batch);

   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   UTF8String TmpBinFile;
   UTF8String TmpXmlFile;
   SOCKET Sock = INVALID_SOCKET;
   DWORD ErrCode;
   int r;
   char ErrStr[200 + 1];
   char Buf[4096 + 1];
   bool FullRefresh = Batch->Entered;
   bool RepeatFlag = false;
   bool ProgressFlag = false;
   bool XmlPropertyFlag = false;
   bool EmptyStatusFile = false;
   UTF8String StatusFileName;
   UTF8String XmlFile;

   Batch->Lock();
   HOutlineStatus OutlineStatus = Batch->OutlineStatus;
   StatusFileName = Batch->StatusFileName;
   Batch->StatusFileName = "";
   Batch->Unlock();

   TmpBinFile.sprintf("%stmp%d_%d.bin", h_g::BinDir.c_str(), Batch->Idx, GetCurrentProcessId());
   TmpXmlFile.sprintf("%stmp%d_%d.xml", h_g::BinDir.c_str(), Batch->Idx, GetCurrentProcessId());

   if ( Outline.Offline )
   {
      XmlFile = StatusFileName;
      if ( XmlFile == "" )
      {
         EmptyStatusFile = true;
      }
   }
   else
   {
      Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
       h_g::WriteLog("Idx = %3d, TmpXmlFile = %s, Sock = %d",
         Batch->Idx, TmpXmlFile.c_str(), Sock);
      if ( Sock == INVALID_SOCKET )
      {
         OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
            "Outline", WSAGetLastError());
         goto error;
      }
      if ( Outline.HotbackFlag )
      {
         r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
            Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
         if ( r < 0 )
         {
            OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
               "Outline", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
            r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
               Outline.Port, COMM_TIME_OUT, &ErrCode);
            if ( r < 0 )
            {
               OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
                  "Outline", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
               goto error;
            }
            OutlineStatus.StatusStr = "";
            Outline.HotbackFlag = false;
         }
      }
      else
      {
         r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
            Outline.Port, COMM_TIME_OUT, &ErrCode);
         if ( r < 0 )
         {
            OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
               "Outline", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
            if ( Outline.HotbackIpAddr == "" )
            {
               goto error;
            }
            r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
               Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
            if ( r < 0 )
            {
               OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
                  "Outline", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
               goto error;
            }
            OutlineStatus.StatusStr = "";
            Outline.HotbackFlag = true;
         }
      }
      Batch->Lock();
      snprintf(Buf, 4096, "%s%s|%s|%s|Y|%s", PVER, FullRefresh ? "4" : "H",
         h_g::ClientCodeSet.c_str(),
         Batch->LastLoginId.c_str(), Batch->LastRefreshTick.c_str());
      Batch->Unlock();
      r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);
      if ( r < 0 )
      {
         OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
            "Outline", r, ErrCode);
         goto error;
      }
      XmlFile = StatusFileName == "" ? TmpXmlFile : StatusFileName;
      if ( !ReadFileFromSocketDecompress(Sock, ErrStr,
               TmpBinFile.c_str(), XmlFile.c_str(),
               RepeatFlag, Batch, ProgressFlag, Outline.Protocol <= "0203") )
      {
         OutlineStatus.StatusStr.sprintf("%s", ErrStr);
         if ( Outline.HotbackFlag )
         {
            Outline.HotbackFlag = false;
         }
         else
         {
            if ( Outline.HotbackIpAddr != "" )
            {
               Outline.HotbackFlag = true;
            }
         }
         goto error;
      }
      closesocket(Sock);
      Sock = INVALID_SOCKET;
      if ( !RepeatFlag )
      {
         if( !TextFileDecompress(TmpBinFile.c_str(), XmlFile.c_str()) )
         {
            OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
               "Outline");
            goto error;
         }
      }
   }

   if ( h_g::ExitFlag || XmlFile == "" )
   {
      goto end;
   }

   Batch->Lock();

   if ( !Batch->RefreshXml->LoadFromFile(XmlFile.c_str()) )
   {
      OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:LOAD_FAIL"),
         XmlFile.c_str(), Batch->RefreshXml->GetErrorString().c_str());
      Batch->Unlock();
      goto error;
   }

   Batch->Unlock();
   OutlineStatus.FullRefresh = FullRefresh;

   {
      vector<string> Version;
      SplitString(Batch->RefreshXml->GetValue("VERSION"), '.', Version);
      if ( Version.size() == 3 )
      {
         int Ver = StrToInt(Version[0].c_str()) * 256 + StrToInt(Version[1].c_str());
         XmlPropertyFlag = ( Ver >= 0x0204 );
      }
   }

   if ( FullRefresh )
   {
      if ( XmlPropertyFlag )
      {
         OutlineStatus.RefreshTick = Batch->RefreshXml->GetProperty("REFRESH_TICK").c_str();
      }
      else
      {
         OutlineStatus.RefreshTick = Batch->RefreshXml->GetValue("REFRESH_TICK").c_str();
      }
   }
   else
   {
      OutlineStatus.RefreshTick = "";
   }

   if ( XmlPropertyFlag )
   {
      OutlineStatus.AutoSkip = Batch->RefreshXml->GetProperty("AUTO_SKIP") == "true";
      OutlineStatus.Banner = Batch->RefreshXml->GetProperty("BANNER").c_str();
      OutlineStatus.AppendLogToSummary = Batch->RefreshXml->GetProperty("APPEND_LOG_TO_SUMMARY") == "true";
      OutlineStatus.ParaJobNum = StrToInt(Batch->RefreshXml->GetProperty("PARA_JOB_NUM").c_str());
      OutlineStatus.CodeSet = Batch->RefreshXml->GetProperty("CODE_SET").c_str();
      OutlineStatus.DailyBatch = Batch->RefreshXml->GetProperty("DAILY_BATCH").c_str();
      OutlineStatus.BatchAlarm = Batch->RefreshXml->GetProperty("BATCH_ALARM").c_str();
      OutlineStatus.Dedicated = Batch->RefreshXml->GetProperty("DEDICATED") == "true";
      OutlineStatus.StatusStr = Batch->RefreshXml->GetProperty("BATCH_STATUS").c_str();
      OutlineStatus.BatchDate = Batch->RefreshXml->GetProperty("BATCH_DATE").c_str();
      OutlineStatus.NextBatchDate = Batch->RefreshXml->GetProperty("NEXT_BATCH_DATE").c_str();
      OutlineStatus.EndBatchDate = Batch->RefreshXml->GetProperty("END_BATCH_DATE").c_str();
      OutlineStatus.NextScheduleDate = Batch->RefreshXml->GetProperty("NEXT_SCHEDULE_DATE").c_str();
   }
   else
   {
      OutlineStatus.AutoSkip = Batch->RefreshXml->GetValue("AUTO_SKIP") == "true";
      OutlineStatus.Banner = Batch->RefreshXml->GetValue("BANNER").c_str();
      OutlineStatus.AppendLogToSummary = Batch->RefreshXml->GetValue("APPEND_LOG_TO_SUMMARY") == "true";
      OutlineStatus.ParaJobNum = StrToInt(Batch->RefreshXml->GetValue("PARA_JOB_NUM").c_str());
      OutlineStatus.CodeSet = Batch->RefreshXml->GetValue("CODE_SET").c_str();
      OutlineStatus.DailyBatch = Batch->RefreshXml->GetValue("DAILY_BATCH").c_str();
      OutlineStatus.BatchAlarm = Batch->RefreshXml->GetValue("BATCH_ALARM").c_str();
      OutlineStatus.Dedicated = Batch->RefreshXml->GetValue("DEDICATED") == "true";
      OutlineStatus.StatusStr = Batch->RefreshXml->GetValue("BATCH_STATUS").c_str();
      OutlineStatus.BatchDate = Batch->RefreshXml->GetValue("BATCH_DATE").c_str();
      OutlineStatus.NextBatchDate = Batch->RefreshXml->GetValue("NEXT_BATCH_DATE").c_str();
      OutlineStatus.EndBatchDate = Batch->RefreshXml->GetValue("END_BATCH_DATE").c_str();
      OutlineStatus.NextScheduleDate = Batch->RefreshXml->GetValue("NEXT_SCHEDULE_DATE").c_str();
   }

   OutlineStatus.Cluster = Batch->RefreshXml->GetValues("CLUSTER").c_str();
   h_g::WriteLog("Idx = %3d, StatusStr = %s", Batch->Idx, OutlineStatus.StatusStr.c_str());

   if ( OutlineStatus.StatusStr == "NOT_STARTED" )
   {
      OutlineStatus.StartTime = "";
      OutlineStatus.EndTime = "";
      OutlineStatus.CompletedRatio = "";
      OutlineStatus.StatusStr = h_g::I18nString("h_server:BATCH_NOT_STARTED");
      OutlineStatus.JobName = "";
      OutlineStatus.Status = h_g::itNormal;
   }
   else if ( OutlineStatus.StatusStr == "STOPPED" )
   {
      if ( XmlPropertyFlag )
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetProperty("BATCH_START_TIME").c_str();
         OutlineStatus.EndTime = Batch->RefreshXml->GetProperty("BATCH_END_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetProperty("COMPLETED_RATIO").c_str();
      }
      else
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetValue("BATCH_START_TIME").c_str();
         OutlineStatus.EndTime = Batch->RefreshXml->GetValue("BATCH_END_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetValue("COMPLETED_RATIO").c_str();
      }
      OutlineStatus.JobName = "";
      OutlineStatus.StatusStr = h_g::I18nString("h_server:BATCH_IS_STOPPED");
      OutlineStatus.Status = h_g::itSuccess;
      if ( Batch->Outline.FadingPeriod != "" )
      {
         int Hour;
         int Min;
         char TmpStr[200 + 1];
         memcpy(TmpStr, Batch->Outline.FadingPeriod.c_str(), 2);
         TmpStr[2] = '\0';
         Hour = StrToInt(TmpStr);
         memcpy(TmpStr, Batch->Outline.FadingPeriod.c_str() + 3, 2);
         TmpStr[2] = '\0';
         Min = StrToInt(TmpStr);
         TDateTime EndTime;
         ToDateTime(FormatDateTime(OutlineStatus.EndTime), EndTime);
         if ( DateTimeToSec(TDateTime::CurrentDateTime() - EndTime) > ( Hour * 60 + Min ) * 60 )
         {
            OutlineStatus.Status = h_g::itNormal;
         }
      }
   }
   else if ( OutlineStatus.StatusStr == "PAUSED" )
   {
      if ( XmlPropertyFlag )
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetProperty("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetProperty("COMPLETED_RATIO").c_str();
      }
      else
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetValue("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetValue("COMPLETED_RATIO").c_str();
      }
      OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:BATCH_IS_PAUSED"));
      OutlineStatus.Status = h_g::itPaused;
   }
   else if ( OutlineStatus.StatusStr == "STARTED" )
   {
      if ( XmlPropertyFlag )
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetProperty("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetProperty("COMPLETED_RATIO").c_str();
      }
      else
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetValue("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetValue("COMPLETED_RATIO").c_str();
      }
      OutlineStatus.EndTime = "";
      OutlineStatus.JobName = "";
      OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:BATCH_IS_STARTED"));
      OutlineStatus.Status = h_g::itRunning;
   }
   else if ( OutlineStatus.StatusStr == "JOB_WAIT" )
   {
      if ( XmlPropertyFlag )
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetProperty("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetProperty("COMPLETED_RATIO").c_str();
         OutlineStatus.JobName = Batch->RefreshXml->GetProperty("JOB_NAME").c_str();
      }
      else
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetValue("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetValue("COMPLETED_RATIO").c_str();
         OutlineStatus.JobName = Batch->RefreshXml->GetValue("JOB_NAME").c_str();
      }
      OutlineStatus.EndTime = "";
      OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:JOB_IS_WAITING"),
         OutlineStatus.JobName.c_str());
      OutlineStatus.Status = h_g::itWaiting;
   }
   else if ( OutlineStatus.StatusStr == "JOB_FAIL" )
   {
      if ( XmlPropertyFlag )
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetProperty("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetProperty("COMPLETED_RATIO").c_str();
         OutlineStatus.JobName = Batch->RefreshXml->GetProperty("JOB_NAME").c_str();
      }
      else
      {
         OutlineStatus.StartTime = Batch->RefreshXml->GetValue("BATCH_START_TIME").c_str();
         OutlineStatus.CompletedRatio = Batch->RefreshXml->GetValue("COMPLETED_RATIO").c_str();
         OutlineStatus.JobName = Batch->RefreshXml->GetValue("JOB_NAME").c_str();
      }
      OutlineStatus.EndTime = "";
      OutlineStatus.StatusStr.sprintf(h_g::I18nString("h_server:JOB_IS_FAILED"), OutlineStatus.JobName.c_str());
      OutlineStatus.Status = h_g::itFailed;
   }

   if ( XmlPropertyFlag )
   {
      OutlineStatus.AlarmType = Batch->RefreshXml->GetProperty("ALARM_TYPE").c_str();
   }
   else
   {
      OutlineStatus.AlarmType = Batch->RefreshXml->GetValue("ALARM_TYPE").c_str();
   }

   if ( OutlineStatus.AlarmType != "" )
   {
      UTF8String AlarmStr;
      UTF8String AlarmJobName;
      if ( XmlPropertyFlag )
      {
         AlarmJobName = Batch->RefreshXml->GetProperty("JOB_NAME").c_str();
      }
      else
      {
         AlarmJobName = Batch->RefreshXml->GetValue("JOB_NAME").c_str();
      }
      if ( OutlineStatus.AlarmType == "JOB_ALARM" )
      {
         OutlineStatus.JobName = AlarmJobName;
         AlarmStr.sprintf(h_g::I18nString("h_server:JOB_IS_NOT_STARTED_YET"), OutlineStatus.JobName.c_str());
      }
      else if ( OutlineStatus.AlarmType == "JOB_ALARM_END" )
      {
         OutlineStatus.JobName = AlarmJobName;
         AlarmStr.sprintf(h_g::I18nString("h_server:JOB_IS_TIMED_OUT"), OutlineStatus.JobName.c_str());
      }
      else if ( OutlineStatus.AlarmType == "BATCH_ALARM_END" )
      {
         OutlineStatus.JobName = AlarmJobName;
         AlarmStr.sprintf(h_g::I18nString("h_server:BATCH_IS_NOT_COMPLETED_YET"),
            Batch->RefreshXml->GetValue("ALARM_BATCH_NAME").c_str());
      }
      else if ( OutlineStatus.AlarmType == "BATCH_ALARM_START" )
      {
         OutlineStatus.JobName = AlarmJobName;
         AlarmStr.sprintf(h_g::I18nString("h_server:BATCH_IS_NOT_STARTED_YET"),
            Batch->RefreshXml->GetValue("ALARM_BATCH_NAME").c_str());
      }
      else if ( OutlineStatus.AlarmType == "FS_CHECK" )
      {
         AlarmStr = h_g::I18nString("h_server:FILE_SYSTEM_IS_ALMOST_FULL");
      }
      else if ( OutlineStatus.AlarmType == "RESTART" )
      {
         AlarmStr = h_g::I18nString("h_server:SYSTEM_IS_RESTARTED");
      }
      else if ( OutlineStatus.AlarmType == "HOTBACK" )
      {
         AlarmStr = h_g::I18nString("h_server:HOTBACK_FAIL");
      }
      OutlineStatus.StatusStr = OutlineStatus.StatusStr + "; " + AlarmStr;
   }

   if ( Batch->Entered && ProgressFlag )
   {
      PostMessage(MainForm->Handle, HM_PROGRESS, 100, 0);
   }

   goto end;

error :

   h_g::WriteLog("Idx = %3d, error, StatusStr = %s",
      Batch->Idx, OutlineStatus.StatusStr.c_str());
   OutlineStatus.Status = h_g::itUnknown;

   if ( ProgressFlag )
   {
      PostMessage(MainForm->Handle, HM_PROGRESS, 0, 1);
      ProgressFlag = false;
   }

end :

   if ( !h_g::DebugFlag )
   {
      DeleteFile(TmpBinFile);
      DeleteFile(TmpXmlFile);
   }

   h_g::WriteLog("Idx = %3d, end, Sock = %d, ExitFlag = %d, RefreshLocked = %d, PaintingFlag = %d",
      Batch->Idx, Sock, h_g::ExitFlag, RefreshLocked, Batch->PaintingFlag);

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   if ( RefreshLocked || h_g::ExitFlag || Batch->PaintingFlag || EmptyStatusFile )
   {
      if ( ProgressFlag )
      {
         PostMessage(MainForm->Handle, HM_PROGRESS, 0, 1);
      }
      return;
   }

   Batch->Lock();
   Batch->NewOutlineStatus = OutlineStatus;
   Batch->Unlock();
   PostMessage(MainForm->Handle, HM_REFRESHCOMPLETE, (long)Batch, 0);
   h_g::WriteLog("Idx = %3d, HServer::FuncOutline end", Batch->Idx);
}

bool __fastcall HServer::FuncRestartJob(HBatchIcon *Batch,
   const UTF8String &Job, const UTF8String &BatchDate,
   const UTF8String &NextBatchDate, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "RestartJob", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "RestartJob", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "RestartJob", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sK|%s|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str(), BatchDate.c_str(), NextBatchDate.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "RestartJob", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "RestartJob", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "RestartJob");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncChangeConfig(HBatchIcon *Batch,
   UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Batch->Lock();
   HOutlineStatus OutlineStatus = Batch->OutlineStatus;
   Batch->Unlock();
   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ChangeConfig", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ChangeConfig", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ChangeConfig", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sM|%s|%s|%s|%d|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), OutlineStatus.AppendLogToSummary ? "true" : "false",
      OutlineStatus.ParaJobNum, OutlineStatus.CodeSet.c_str(),
      OutlineStatus.DailyBatch.c_str(), OutlineStatus.BatchAlarm.c_str(),
      OutlineStatus.Dedicated ? "true" : "false");
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "ChangeConfig", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "ChangeConfig", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "ChangeConfig");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

bool __fastcall HServer::FuncChangeJobCondition(HBatchIcon *Batch,
   const UTF8String &JobName, bool CondNot, const UTF8String &ConditionFile,
   const UTF8String &SpecialDate, const UTF8String &LoopStartTime,
   const UTF8String &LoopEndTime, UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "ChangeJobCondition", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ChangeJobCondition", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "ChangeJobCondition", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sj|%s|%s|%s|%s|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), JobName.c_str(), CondNot ? "Y" : "N",
      ConditionFile.c_str(), SpecialDate.c_str(),
      LoopStartTime.c_str(), LoopEndTime.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "ChangeJobCondition", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "ChangeJobCondition", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "ChangeJobCondition");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

void __fastcall HServer::FuncDownload(HBatchIcon *Batch,
   const UTF8String &SrcFileName, const UTF8String &DesFileName)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int TotalLen, Len, i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[4096 + 1];
   HXmlTree Xml;
   char TmpFile1[500 + 1];
   char TmpFile2[500 + 1];

   snprintf(TmpFile1, 200, "t1_%d_%ld", Batch->Idx, GetCurrentProcessId());
   snprintf(TmpFile2, 200, "%s", DesFileName.c_str());

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "Download", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "Download", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         snprintf(Buf, 200, h_g::I18nString("h_server:CONNECT_ERROR"),
            "Download", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 4096, "%sU|%s|%s|%s|", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), SrcFileName.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:WRITE_ERROR"),
         "Download", r, ErrCode);
      goto error;
   }

   if ( !ReadFileFromSocket(Sock, Buf, TmpFile1) )
   {
      goto error;
   }

   if( !TextFileDecompress(TmpFile1, TmpFile2) )
   {
      snprintf(Buf, 200, h_g::I18nString("h_server:TEXT_FILE_DECOMPRESS_FAIL"),
         "Download");
      goto error;
   }

   DeleteFile(TmpFile1);
   closesocket(Sock);
   Sock = INVALID_SOCKET;
   snprintf(Buf, 4096, h_g::I18nString("h_server:DOWNLOAD_COMPLETED"), TmpFile2);
   h_g::ShowMessage(UTF8String(Buf));
   return;

error :

   DeleteFile(TmpFile1);
   h_g::ShowMessage(UTF8String(Buf));

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);
}

bool __fastcall HServer::FuncBreakpoint(HBatchIcon *Batch,
   const UTF8String &Job, const UTF8String &SetUnset,
   UTF8String &ErrorString)
{
   const HBatchOutline &Outline = Batch->Outline;
   const char *PVER = Outline.Protocol <= "0103" ? "" : ProtocolVersion;

   int i, r;
   SOCKET Sock;
   DWORD ErrCode;
   char Buf[8192 + 1];

   Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   if( Sock == INVALID_SOCKET )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:CREATE_SOCKET_ERROR"),
         "Breakpoint", WSAGetLastError());
      goto error;
   }

   if ( Outline.HotbackFlag )
   {
      r = HComm::Connect(Sock, Outline.HotbackIpAddr.c_str(),
         Outline.HotbackPort, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "Breakpoint", Outline.HotbackIpAddr.c_str(), Outline.HotbackPort, r, ErrCode);
         goto error;
      }
   }
   else
   {
      r = HComm::Connect(Sock, Outline.IpAddr.c_str(),
         Outline.Port, COMM_TIME_OUT, &ErrCode);
      if( r < 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:CONNECT_ERROR"),
            "Breakpoint", Outline.IpAddr.c_str(), Outline.Port, r, ErrCode);
         goto error;
      }
   }

   snprintf(Buf, 8192, "%sr|%s|%s|%s|%s", PVER, h_g::ClientCodeSet.c_str(),
      Batch->LastLoginId.c_str(), Job.c_str(), SetUnset.c_str());
   r = HComm::WriteByLength(Sock, Buf, strlen(Buf), COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:WRITE_ERROR"),
         "Breakpoint", r, ErrCode);
      goto error;
   }

   r = HComm::Read(Sock, Buf, 1, COMM_TIME_OUT, &ErrCode);

   if( r < 0 )
   {
      ErrorString.sprintf(h_g::I18nString("h_server:READ_ERROR"),
         "Breakpoint", r, ErrCode);
      goto error;
   }

   if( Buf[0] != '0' )
   {
      int Len;
      r = HComm::ReadByLength(Sock, Buf, Len, COMM_TIME_OUT, &ErrCode);
      if ( r != 0 )
      {
         ErrorString.sprintf(h_g::I18nString("h_server:FAIL"),
            "Breakpoint");
      }
      else
      {
         Buf[Len] = '\0';
         ErrorString = Buf;
      }
      goto error;
   }

   closesocket(Sock);
   return true;

error :

   if( Sock != INVALID_SOCKET )
      closesocket(Sock);

   return false;
}

#pragma package(smart_init)
